package sk.mka.phd.googleagent.ngram.statistics;

import java.io.BufferedWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.logging.Level;
import org.apache.log4j.Logger;
import sk.mka.phd.files.reader.load.ILoadData;
import sk.mka.phd.files.reader.load.arbitrary.ArbitraryDataLoadFileImpl;
import sk.mka.phd.googleagent.ngram.IGoogleNgram;
import sk.mka.phd.googleagent.statistics.AbstractStatisticsAgent;
import sk.mka.phd.googleagent.statistics.IGoogleStatisticsAgent;
import sk.mka.utils.tools.filesystem.FileUtils;

/**
 * This file combine ngram creation with statistics, which is working together
 * @author bracek
 * @date Jul 22, 2010
 */
public final class NgramImpl extends AbstractStatisticsAgent implements IGoogleNgram {

    private static final Logger log = Logger.getLogger(NgramImpl.class);
    private ArrayList incomingArrayList = new ArrayList();
    private BufferedWriter refusedWordsOutput;
    private final IGoogleStatisticsAgent googleStatisticsAgent;
    private BufferedWriter bufferedWriter;

    public NgramImpl(IGoogleStatisticsAgent statisticsAgent, final String separator) {
        super();
        this.googleStatisticsAgent = statisticsAgent;
        this.squareDataLoadFile = new ArbitraryDataLoadFileImpl(dictionaryInput, separator);
    }

    private void loadInputData() {
        ((ILoadData) squareDataLoadFile).loadData();
        ArrayList<Object> linesHashSet = squareDataLoadFile.getLines();
        for (Object object : linesHashSet) {
            incomingArrayList.add(object);
        }
    }

    @Override
    public void createNgramModel() {

        for (int i = 0; i < ngram; i++) {

            try {
                loadInputData();
                ArrayList tmp = new ArrayList();
                for (Object object : incomingArrayList) {
                    ArrayList<Object> col = (ArrayList<Object>) object;
                    tmp.add(col);
                }

                FileUtils.delete(dictionaryInput);
                bufferedWriter = FileUtils.openFileForWriting(dictionaryInput, true);

                try {
                    // go throught all words in dictionary
                    for (Object singleLineWord : incomingArrayList) {
                        ArrayList<Object> col = (ArrayList<Object>) singleLineWord;
                        bufferOutput = FileUtils.openFileForWriting(ngramOutputFileName, true);
                        if (writeRefusedWordsFromDictionary) {
                            refusedWordsOutput = FileUtils.openFileForWriting(refusedWordsFromDictionary, true);
                        }
                        generateAllCombinationForWord(col, tmp, bufferOutput, bufferedWriter, refusedWordsOutput);
                        bufferOutput.close();
                        if (refusedWordsOutput != null) {
                            refusedWordsOutput.close();
                        }
                    }
                    bufferedWriter.close();

                    writeBufferToFile();

                } catch (IOException ex) {
                    log.fatal(ex);
                }

            } catch (IOException ex) {
                java.util.logging.Logger.getLogger(NgramImpl.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

    //TODO cross out same word for combination (founded when trying quatrogram :) 
    /**
     * @param line
     * @param allWords
     * @param bufferOutput all words with achieved occurrence
     * @param refusedWordsOutput contains all words, whose get no result from Internet about word occurrence
     */
    private void generateAllCombinationForWord(final ArrayList line, final ArrayList allWords, final BufferedWriter bufferOutput, BufferedWriter dictionaryOTemporaryOputput, BufferedWriter refusedOutput) {

        if (!finalSet.contains(line)) {
            // make statistics only once for each word or combination of words
            System.out.println("line = " + line);
            boolean hasResult = googleStatisticsAgent.getStatistic(line, bufferOutput, refusedOutput);
            if (hasResult) {
                finalSet.add(line); //add word(s) to final set
            }
        }

        log.warn(line);
        for (Object object1 : allWords) {

            ArrayList<Object> newLine = (ArrayList<Object>) object1;
            boolean write = true;
            if (newLine.size() + line.size()
                    <= ngram) {

                if (line.size() >= newLine.size()) {
                    if (line.containsAll(newLine)) {
                        write = false;
                    }
                } else {

                    if (newLine.containsAll(line)) {
                        write = false;
                    }
                }

                if (write) {
                    if (!newLine.equals(line)) {
                        ArrayList newArray = new ArrayList();
                        for (Object object : line) {
                            newArray.add(object);
                        }

                        for (Object object : newLine) {
                            newArray.add(object);
                        }


                        if (areAraysItemsDifferent(line, newArray)) {

                            if (!line.equals(newArray) || !newArray.equals(line)) {
                                if (!finalSet.contains(newArray)) {
                                    finalSet.add(newArray);
                                    googleStatisticsAgent.getStatistic(newArray, bufferOutput, refusedOutput);
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    private boolean areAraysItemsDifferent(ArrayList line, ArrayList newArray) {

        boolean bReturn = true;



        if (line.size() >= newArray.size()) {
            for (Object object : line) {
                if (newArray.indexOf(object) > 0) {
                    bReturn = false;
                    break;
                }
            }
        } else {
            for (Object object : newArray) {
                if (line.indexOf(object) > 0) {
                    bReturn = false;
                    break;
                }
            }
        }

        return bReturn;

    }

    void doStatistics() {

        try {
            loadInputData();

            if (writeRefusedWordsFromDictionary) {
                refusedWordsOutput = FileUtils.openFileForWriting(refusedWordsFromDictionary, true);
            }
            bufferOutput = FileUtils.openFileForWriting(ngramOutputFileName, true);
            for (Object object : incomingArrayList) {
                ArrayList<Object> col = (ArrayList<Object>) object;
                googleStatisticsAgent.getStatistic(col, bufferOutput, refusedWordsOutput);
            }
            bufferOutput.close();
            if (refusedWordsOutput != null) {
                refusedWordsOutput.close();
            }
        } catch (IOException ex) {
            java.util.logging.Logger.getLogger(NgramImpl.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
} //end of cycle going throught all words in vocabulary

